home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / REALITY / distort / ripple.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  5KB  |  236 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.     ripple.c
  19.     Drew Olbrich, 1992
  20.  
  21.     This distortion effect approximates looking down at an
  22.     image through a layer of water.  The user can poke
  23.     at the water using the mouse, generating one or more
  24.     ripple patterns.
  25.  
  26.     To create the effect, an large texture image is mapped
  27.     onto a mesh of polygons.  Only the texture coordinates of
  28.     the polygon vertices are distorted -- not the vertex
  29.     coordinates.
  30. */
  31.  
  32. #include <stdio.h>
  33. #include <math.h>
  34. #include <gl.h>
  35. #include <device.h>
  36.  
  37. #include "defs.h"
  38. #include "ripple.h"
  39.  
  40. EFFECT ripple = { ripple_init, ripple_dynamics, ripple_redraw, ripple_click };
  41.  
  42. static RIPPLE_VERTEX ripple_vertex[GRID_SIZE_X][GRID_SIZE_Y];
  43.  
  44. static int cx[RIPPLE_COUNT];
  45. static int cy[RIPPLE_COUNT];
  46. static int t[RIPPLE_COUNT];
  47. static int max[RIPPLE_COUNT];
  48.  
  49. static int ripple_max;
  50.  
  51. /*
  52.     Initialize ripple location and age information.
  53.  
  54.     Also, precompute the vertex coordinates and the default texture
  55.     coordinates assigned to them.
  56. */
  57.  
  58. void ripple_init()
  59. {
  60.   int i, j;
  61.  
  62.   zbuffer(FALSE);
  63.  
  64.   ripple_max = (int) sqrt(WIN_SIZE_X*WIN_SIZE_X + WIN_SIZE_Y*WIN_SIZE_Y);
  65.  
  66.   for (i = 0; i < RIPPLE_COUNT; i++)
  67.   {
  68.     t[i] = ripple_max + RIPPLE_LENGTH;
  69.     cx[i] = 0;
  70.     cy[i] = 0;
  71.     max[i] = 0;
  72.   }
  73.  
  74.   for (i = 0; i < GRID_SIZE_X; i++)
  75.     for (j = 0; j < GRID_SIZE_Y; j++)
  76.     {
  77.       ripple_vertex[i][j].x[0] = i/(GRID_SIZE_X - 1.0)*WIN_SIZE_X;
  78.       ripple_vertex[i][j].x[1] = j/(GRID_SIZE_Y - 1.0)*WIN_SIZE_Y;
  79.       ripple_vertex[i][j].dt[0] = i/(GRID_SIZE_X - 1.0);
  80.       ripple_vertex[i][j].dt[1] = j/(GRID_SIZE_Y - 1.0);
  81.     }
  82. }
  83.  
  84. /*
  85.     Advance one time step and compute new texture coordinates
  86.     for the next frame of animation.
  87. */
  88.  
  89. void ripple_dynamics(int mousex, int mousey)
  90. {
  91.   int i, j, k;
  92.   int x, y;
  93.   int mi, mj;
  94.   int r;
  95.   float sx, sy;
  96.   float amp;
  97.  
  98.   for (i = 0; i < RIPPLE_COUNT; i++)
  99.     t[i] += RIPPLE_STEP;
  100.  
  101.   for (i = 0; i < GRID_SIZE_X; i++)
  102.     for (j = 0; j < GRID_SIZE_Y; j++)
  103.     {
  104.       ripple_vertex[i][j].t[0] = ripple_vertex[i][j].dt[0];
  105.       ripple_vertex[i][j].t[1] = ripple_vertex[i][j].dt[1];
  106.  
  107.       for (k = 0; k < RIPPLE_COUNT; k++)
  108.       {
  109.     x = i - cx[k];
  110.     y = j - cy[k];
  111.     if (x < 0)
  112.     {
  113.       x *= -1;
  114.       sx = -1.0;
  115.     }
  116.     else
  117.       sx = 1.0;
  118.     if (y < 0)
  119.     {
  120.       y *= -1;
  121.       sy = -1.0;
  122.     }
  123.     else
  124.       sy = 1.0;
  125.     mi = x;
  126.     mj = y;
  127.     
  128.     r = t[k] - ripple_vector[mi][mj].r;
  129.     
  130.     if (r < 0)
  131.       r = 0;
  132.     if (r > RIPPLE_LENGTH - 1)
  133.       r = RIPPLE_LENGTH - 1;
  134.  
  135.     amp = 1.0 - 1.0*t[k]/RIPPLE_LENGTH;
  136.     amp *= amp;
  137.     if (amp < 0.0)
  138.       amp = 0.0;
  139.     
  140.     ripple_vertex[i][j].t[0]
  141.       += ripple_vector[mi][mj].dx[0]*sx*ripple_amp[r].amplitude*amp;
  142.     ripple_vertex[i][j].t[1]
  143.       += ripple_vector[mi][mj].dx[1]*sy*ripple_amp[r].amplitude*amp;
  144.       }
  145.     }
  146. }
  147.  
  148. /*
  149.     Draw the next frame of animation.
  150. */
  151.  
  152. void ripple_redraw()
  153. {
  154.   int i, j;
  155.  
  156.   cpack(0xFFFFFFFF);
  157.  
  158.   for (i = 0; i < GRID_SIZE_X - 1; i++)
  159.   {
  160.     for (j = 0; j < GRID_SIZE_Y - 1; j++)
  161.     {
  162.       bgnpolygon();
  163.       t2f(ripple_vertex[i][j].t);
  164.       v2f(ripple_vertex[i][j].x);
  165.       t2f(ripple_vertex[i][j + 1].t);
  166.       v2f(ripple_vertex[i][j + 1].x);
  167.       t2f(ripple_vertex[i + 1][j + 1].t);
  168.       v2f(ripple_vertex[i + 1][j + 1].x);
  169.       t2f(ripple_vertex[i + 1][j].t);
  170.       v2f(ripple_vertex[i + 1][j].x);
  171.       endpolygon();
  172.     }
  173.   }
  174.  
  175.   swapbuffers();
  176. }
  177.  
  178. /*
  179.     Calculate the distance between two points.
  180. */
  181.  
  182. float ripple_distance(int gx, int gy, int cx, int cy)
  183. {
  184.   return sqrt(1.0*(gx - cx)*(gx - cx) + 1.0*(gy - cy)*(gy - cy));
  185. }
  186.  
  187. /*
  188.     Compute the distance of the given window coordinate
  189.     to the nearest window corner, in pixels.
  190. */
  191.  
  192. int ripple_max_distance(int gx, int gy)
  193. {
  194.   float d;
  195.   float temp_d;
  196.  
  197.   d = ripple_distance(gx, gy, 0, 0);
  198.   temp_d = ripple_distance(gx, gy, GRID_SIZE_X, 0);
  199.   if (temp_d > d)
  200.     d = temp_d;
  201.   temp_d = ripple_distance(gx, gy, GRID_SIZE_X, GRID_SIZE_Y);
  202.   if (temp_d > d)
  203.     d = temp_d;
  204.   temp_d = ripple_distance(gx, gy, 0, GRID_SIZE_Y);
  205.   if (temp_d > d)
  206.     d = temp_d;
  207.  
  208.   return (d/GRID_SIZE_X)*WIN_SIZE_X + RIPPLE_LENGTH/6;
  209. }
  210.  
  211. /*
  212.     Generate a new ripple when the mouse is pressed.  There's
  213.     a limit on the number of ripples that can be simultaneously
  214.     generated.
  215. */
  216.  
  217. void ripple_click(int mousex, int mousey, int state)
  218. {
  219.   int index;
  220.  
  221.   if (state)
  222.   {
  223.     index = 0;
  224.     while (t[index] < max[index] && index < RIPPLE_COUNT)
  225.       index++;
  226.     
  227.     if (index < RIPPLE_COUNT)
  228.     {
  229.       cx[index] = 1.0*mousex/WIN_SIZE_X*GRID_SIZE_X;
  230.       cy[index] = 1.0*mousey/WIN_SIZE_Y*GRID_SIZE_Y;
  231.       t[index] = 4*RIPPLE_STEP;
  232.       max[index] = ripple_max_distance(cx[index], cy[index]);
  233.     }
  234.   }
  235. }
  236.